package com.bicon.botu.core.base.validate;


import com.bicon.botu.core.base.common.BusinessException;
import com.bicon.botu.core.base.common.Constants;
import com.bicon.botu.core.base.common.Enum.StatusCode;
import com.bicon.botu.core.base.validate.parser.*;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * 对象属性校验类
 * <p>
 * 使用方法, BeanFieldValidator.getInstance().validate(targetObj)
 * 如果需要忽略掉已经通过注解标注的属性，可以通过
 * BeanFieldValidator.getInstance().ignore(fieldName).validate(targetSSSSObj) 或者
 * BeanFieldValidator.getInstance().ignore(new String[]{fieldName1,fieldName2,fieldName3}).validate(targetSSSSObj)
 *
 * @version 1.0.0
 * @author: Gyb
 * @date 2018/2/28
 * @description
 **/
public class BeanFieldValidator extends AbstractValidator {

    private volatile static BeanFieldValidator instance = null;
    private List<String> ignoreFields = new ArrayList<>();

    private BeanFieldValidator() {
        initParsers();
    }

    private void initParsers() {
        getInternalParsers().clear();
        getInternalParsers().add(new NotNullParser());
        getInternalParsers().add(new NotNullOrEmptyParser());
        getInternalParsers().add(new MaxParser());
        getInternalParsers().add(new MinParser());
        getInternalParsers().add(new LengthParser());
        getInternalParsers().add(new SizeParser());
        getInternalParsers().add(new PatternParser());
        getInternalParsers().add(new EmailParser());
        getInternalParsers().add(new MobileParser());
    }

    public static BeanFieldValidator getInstance() {
        if (instance == null) {
            synchronized (BeanFieldValidator.class) {
                if (instance == null) {
                    instance = new BeanFieldValidator();
                }
            }
        }
        return instance;
    }

    @Override
    public void validate(Object o) {
        if (o == null) {
            throw new BusinessException(StatusCode.MISSING_REQUIRE_FIELD.getStatusCode(), StatusCode.MISSING_REQUIRE_FIELD.getStatusMessage());
        }
        Field[] fields = o.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);

            if (ignoreFields.contains(field.getName()) || field.getAnnotations().length == 0) {
                continue;
            }

            Object value = null;
            try {
                value = field.get(o);
            } catch (IllegalAccessException ignore) {
            }

            for (Parser parser : getInternalParsers()) {
                Result result = parser.parse(field, value);
                if (result != null && !result.isPassed()) {
                    throw new BusinessException(Constants.RESPONSE_CODE_400, result.getMessage());
                }
            }
        }
    }

    public Validator ignore(String... fields) {
        for (String field : fields) {
            if (!ignoreFields.contains(field)) {
                ignoreFields.add(field);
            }
        }
        return this;
    }
}
